package tom.vertx.core.demo01;

import io.vertx.core.DeploymentOptions;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.json.JsonObject;
import io.vertx.spi.cluster.zookeeper.ZookeeperClusterManager;
import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.function.Consumer;

/**
 * @author ZHUFEIFEI
 */
@Slf4j
public class DeployVerticleDemo {

  public static void main(String[] args) {
    JsonObject jsonObject = new JsonObject();
    jsonObject.put("workerPoolName", "myWorkerPool");
    Vertx.vertx().deployVerticle(new HelloVerticle(), new DeploymentOptions(jsonObject));
  }

  /**
   * HA部署,当一个实例意外终止,将会重新部署另一个实例到集群中, 需要clusterManager支持(支持编码设定\spi\命令行参数设置,见源码)
   * 引入vertx-zookeeper, 本地启动zookeeper
   * @param args
   */
  public static void main1111(String[] args) {
    Consumer<Vertx> consumer = v -> v.deployVerticle(new HelloVerticle());
    //使用方式参照ZookeeperClusterManager源码
    Vertx.clusteredVertx(new VertxOptions().setHAEnabled(true).setHAGroup("ha-1").setClusterManager(new ZookeeperClusterManager()), res -> {
      if (res.succeeded()) {
        consumer.accept(res.result());
        log.info("ha-cluster successed.");
      } else {
        res.cause().printStackTrace();
      }
    });
    //vertx内的线程为非伴随线程,会组织jvm退出,如果需要退出,使用vertx.close()将会关闭线程池内所有线程,并停止vertx
  }


  /**
   * 部署隔离,可以同时部署不同版本的Verticle, 隔离依赖等操作. 多数情况不需要该操作, 下面的实验虽然设置了隔离但是最终还是由同一个AppClassloader加载的
   * @param args
   */
  public static void main111(String[] args) {
    DeploymentOptions deploymentOptions = new DeploymentOptions();
    //隔离组
    deploymentOptions.setIsolationGroup("iso-1");
    //隔离类, 使用不同的classloader加载, 注意只有父类classloader没有加载该类的时候, 才会有IsolatingClassloader加载,并且遵循双亲委派原则
    deploymentOptions.setIsolatedClasses(Arrays.asList("tom.vertx.util.MainRunner"));
    //隔离依赖, 可以使用不同版本的依赖库
//    deploymentOptions.setExtraClasspath(Arrays.asList("lib1"));
    Vertx vertx = Vertx.vertx();
    vertx.deployVerticle("tom.vertx.demo01.HelloVerticle", deploymentOptions, res -> {
      //verticle通过verticleFactory实例化启动, factory在vertx启动时加载注册
      vertx.verticleFactories().forEach(v -> log.info("factory1 prefix => {}", v.toString()));
    });

    DeploymentOptions deploymentOptions1 = new DeploymentOptions();
    deploymentOptions1.setIsolationGroup("iso-2");
    deploymentOptions1.setIsolatedClasses(Arrays.asList("tom.vertx.util.*"));
    vertx.deployVerticle("tom.vertx.demo01.HelloVerticle", deploymentOptions1, res -> {
      //verticle通过verticleFactory实例化启动, factory在vertx启动时加载注册
      vertx.verticleFactories().forEach(v -> log.info("factory2 prefix => {}", v.toString()));
    });


  }

  /**
   * 部署与卸载
   * @param args
   */
  public static void main11(String[] args) {
    Vertx vertx = Vertx.vertx();
    HelloVerticle hello = new HelloVerticle();

    Consumer<Vertx> consumer = vertx1 -> {
      //卸载verticle
      vertx1.undeploy(hello.deploymentID(), res -> {
        if (res.succeeded()) {
          log.info("Undeploy ok => {}", res);
        } else {
          log.info("unDeploy failed.");
        }
      });
    };

    vertx.deployVerticle(hello, result -> {
      if (result.succeeded()) {
        log.info("Deployment id => {}", result.result());
        consumer.accept(vertx);
      } else {
        log.info("Deploy failed.");
      }
    });


  }

  /**
   * 简单部署
   * @param args
   */
  public static void main1(String[] args) {
    Vertx vertx = Vertx.vertx();
    //下面两种方式等效, 此外还可以通过DeploymentOptions VertxOptions配置其他属性
    vertx.deployVerticle(new HelloVerticle());
    vertx.deployVerticle("tom.vertx.demo01.HelloVerticle");
  }

}
